/**
 * ReportGear(2011)
 */
package net.abbp.report.model.headerfooter;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import net.abbp.report.model.cell.style.FontStyle;

import com.reportgear.report.model.headerfooter.paintable.HFPaintable;
import com.reportgear.report.model.headerfooter.paintable.TextHFPaintable;

/**
 * 报表页脚页眉-信息
 * 
 * @version 1.0 2011-4-23
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public class ReportHF extends ReportHFCore {
	private static final int TYPE_LEFT = 0;
	private static final int TYPE_CENTER = 1;
	private static final int TYPE_RIGHT = 2;

	public void addLeftText(String text, FontStyle fontStyle) {
		addLeftText(-1, text, fontStyle);
	}

	public void addLeftText(int index, String text, FontStyle fontStyle) {
		addHFElement(TYPE_LEFT, index, new TextHFElement(text, fontStyle));
	}

	public void addCenterText(String text, FontStyle fontStyle) {
		addCenterText(-1, text, fontStyle);
	}

	public void addCenterText(int index, String text, FontStyle fontStyle) {
		addHFElement(TYPE_CENTER, index, new TextHFElement(text, fontStyle));
	}

	public void addRightText(String text, FontStyle fontStyle) {
		addRightText(-1, text, fontStyle);
	}

	public void addRightText(int index, String text, FontStyle fontStyle) {
		addHFElement(TYPE_RIGHT, index, new TextHFElement(text, fontStyle));
	}

	public void addLeftPageNumber(FontStyle fontStyle) {
		addLeftPageNumber(-1, fontStyle);
	}

	public void addLeftPageNumber(int index, FontStyle fontStyle) {
		addHFElement(TYPE_LEFT, index, new PageNumHFElement(fontStyle));
	}

	public void addCenterPageNumber(FontStyle fontStyle) {
		addCenterPageNumber(-1, fontStyle);
	}

	public void addCenterPageNumber(int index, FontStyle fontStyle) {
		addHFElement(TYPE_CENTER, index, new PageNumHFElement(fontStyle));
	}

	public void addRightPageNumber(FontStyle fontStyle) {
		addRightPageNumber(-1, fontStyle);
	}

	public void addRightPageNumber(int index, FontStyle fontStyle) {
		addHFElement(TYPE_RIGHT, index, new PageNumHFElement(fontStyle));
	}

	public void addLeftNumberOfPage(FontStyle fontStyle) {
		addLeftNumberOfPage(-1, fontStyle);
	}

	public void addLeftNumberOfPage(int index, FontStyle fontStyle) {
		addHFElement(TYPE_LEFT, index, new TotalPagesHFElement(fontStyle));
	}

	public void addCenterNumberOfPage(FontStyle fontStyle) {
		addCenterNumberOfPage(-1, fontStyle);
	}

	public void addCenterNumberOfPage(int index, FontStyle fontStyle) {
		addHFElement(TYPE_CENTER, index, new TotalPagesHFElement(fontStyle));
	}

	public void addRightNumberOfPage(FontStyle fontStyle) {
		addRightNumberOfPage(-1, fontStyle);
	}

	public void addRightNumberOfPage(int index, FontStyle fontStyle) {
		addHFElement(TYPE_RIGHT, index, new TotalPagesHFElement(fontStyle));
	}

	private void addHFElement(int type, int index, HFElement paramHFElement) {
		if (type == TYPE_RIGHT)
			if ((index == -1) || (index >= getRightList().size()))
				getRightList().add(paramHFElement);
			else
				getRightList().add(index, paramHFElement);
		else if (type == TYPE_CENTER)
			if ((index == -1) || (index >= getCenterList().size()))
				getCenterList().add(paramHFElement);
			else
				getCenterList().add(index, paramHFElement);
		else {
			if ((index == -1) || (index >= getLeftList().size()))
				getLeftList().add(paramHFElement);
			else
				getLeftList().add(index, paramHFElement);
		}
	}

	public void paint(Graphics g, Rectangle2D rect, int pageWidth, int pageNumber, int totalPages, int groupPageNum,
			int groupTotalPages) {
		List<HFPaintable> paintableList = toPaintableList(pageWidth, pageNumber, totalPages, groupPageNum,
				groupTotalPages);

		Graphics2D g2 = (Graphics2D) g;
		Shape oldClip = g2.getClip();
		g2.clip(rect);
		g2.translate(rect.getX(), rect.getY());

		for (HFPaintable p : paintableList) {
			p.paint(g2);
		}

		g2.translate(-rect.getX(), -rect.getY());
		g2.setClip(oldClip);
	}

	private List<HFPaintable> toPaintableList(int pageWidth, int pageNumber, int totalPages, int groupPageNum,
			int groupTotalPages) {
		List<HFPaintable> result = new ArrayList<HFPaintable>();

		this.dealLeftElements(pageNumber, totalPages, groupPageNum, groupTotalPages, result);
		this.dealCenterElements(pageWidth, pageNumber, totalPages,groupPageNum, groupTotalPages, result);
		this.dealRightElements(pageWidth, pageNumber, totalPages,groupPageNum, groupTotalPages,  result);

		return result;
	}

	// 处理页眉页脚左
	private void dealLeftElements(int pageNumber, int totalPages, int groupPageNum, int groupTotalPages,
			List<HFPaintable> result) {
		HFPaintable paintable;
		double x = 0.0D;
		double y = 0.0D;
		List<HFElement> tempList = new ArrayList<HFElement>();
		for (HFElement element : getLeftList()) {
			paintable = createPaintable(element, pageNumber, totalPages, groupPageNum, groupTotalPages);
			paintable.setPaintLocation(new Point2D.Double(x, y));
			if (element instanceof NewLineHFElement) {
				x = 0.0D;

				if (tempList.isEmpty()) {
					y += element.getSize().getHeight();
				} else {
					double yMax = 0;
					for (HFElement el : tempList) {
						yMax = Math.max(yMax, el.getSize().getHeight());
					}
					y += yMax;
				}

				tempList.clear();
			} else {
				x += element.getSize().getWidth();
				result.add(paintable);
				tempList.add(element);
			}
		}
	}

	private void dealCenterElements(int pageWidth, int pageNumber, int totalPages, int groupPageNum,
			int groupTotalPages, List<HFPaintable> result) {
		List<List<HFElement>> tempList = new ArrayList<List<HFElement>>();
		List<HFElement> rowList = new ArrayList<HFElement>();

		for (HFElement element : getCenterList()) {
			if (element instanceof NewLineHFElement) {
				tempList.add(rowList);
				rowList = new ArrayList<HFElement>();
			} else {
				rowList.add(element);
			}
		}

		if (!rowList.isEmpty()) {
			tempList.add(rowList);
		}

		double y = 0.0D;
		for (List<HFElement> es : tempList) {
			double w = 0;
			double yMax = 0;
			for (HFElement el : es) {
				w += el.getSize().getWidth();
				yMax = Math.max(yMax, el.getSize().getHeight());
			}

			double x = (pageWidth - w) / 2;
			for (HFElement el : es) {
				HFPaintable paintable = createPaintable(el, pageNumber, totalPages, groupPageNum, groupTotalPages);
				paintable.setPaintLocation(new Point2D.Double(x, y));

				result.add(paintable);

				x += el.getSize().getWidth();
			}

			y += yMax;
		}
	}

	private void dealRightElements(int pageWidth, int pageNumber, int totalPages, int groupPageNum,
			int groupTotalPages, List<HFPaintable> result) {
		List<List<HFElement>> tempList = new ArrayList<List<HFElement>>();
		List<HFElement> rowList = new ArrayList<HFElement>();

		for (HFElement element : getRightList()) {
			if (element instanceof NewLineHFElement) {
				tempList.add(rowList);
				rowList = new ArrayList<HFElement>();
			} else {
				rowList.add(element);
			}
		}

		if (!rowList.isEmpty()) {
			tempList.add(rowList);
		}

		double y = 0.0D;
		for (List<HFElement> es : tempList) {
			double w = 0;
			double yMax = 0;
			for (HFElement el : es) {
				w += el.getSize().getWidth();
				yMax = Math.max(yMax, el.getSize().getHeight());
			}

			double x = pageWidth - w;
			for (HFElement el : es) {
				HFPaintable paintable = createPaintable(el, pageNumber, totalPages, groupPageNum, groupTotalPages);
				paintable.setPaintLocation(new Point2D.Double(x, y));

				result.add(paintable);

				x += el.getSize().getWidth();
			}

			y += yMax;
		}
	}

	private HFPaintable createPaintable(HFElement element, int pageNumber, int totalPages, int groupPageNum,
			int groupTotalPages) {
		if (element instanceof PageNumHFElement) {
			((PageNumHFElement) element).setText("" + pageNumber);
		} else if (element instanceof TotalPagesHFElement) {
			((TotalPagesHFElement) element).setText("" + totalPages);
		} else if (element instanceof GroupPageNumHFElement) {
			((GroupPageNumHFElement) element).setText("" + groupPageNum);
		} else if (element instanceof GroupTotalPagesHFElement) {
			((GroupTotalPagesHFElement) element).setText("" + groupTotalPages);
		}

		if (element instanceof TextHFElement) {
			return new TextHFPaintable((TextHFElement) element);
		}

		return new TextHFPaintable(new TextHFElement());
	}

	@Override
	public ReportHF clone() {
		return (ReportHF) super.clone();
	}
}
